/*
 * ImageRetriever.java
 *
 * Created on April 19, 2007, 12:20 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package org.voidness.twittava.remoteimages;

import java.awt.Image;
import java.awt.Panel;
import java.awt.image.ImageProducer;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import javax.swing.SwingWorker;

/**
 *
 * @author void
 */
public class ImageRetriever {
    
    private static ImageRetriever instance = null;
    private Map<String, Image> cache = null;
    private Map<String, Collection<RemoteImageListener>> listeners = null;
    
    /** Creates a new instance of ImageRetriever */
    private ImageRetriever() {
        cache = new HashMap<String, Image>();
        listeners = new HashMap<String, Collection<RemoteImageListener>>();
    }
    
    public static ImageRetriever getInstance() {
        if (instance == null) {
            instance = new ImageRetriever();
        }
        return instance;
    }
    
    private void debug(String message) {
        //System.out.println(message);
    }
    
    public synchronized void getImage(final String key, RemoteImageListener listener) {
        if (cache.get(key) == null) {
            debug("Image not found in cache");
            Collection<RemoteImageListener> imageListeners = listeners.get(key);
            if (imageListeners == null) {
                debug("Image not queued for retrieval. Starting worker.");
                // This image is not queued for retrieval, so create the listeners
                // collection
                imageListeners = new ArrayList<RemoteImageListener>();
                listeners.put(key, imageListeners);
                debug("Adding the listener: " + listener);
                imageListeners.add(listener);
                
                // Start a worker to download the image and store it in memory
                new SwingWorker<Object, Object>() {
                    @Override
                    public Object doInBackground() {
                        debug("Starting worker for image: " + key);
                        return downloadImage(key);
                    }
                }.execute();
            } else {
                // Already queued for retrieval, so just add the listener to the list
                debug("Image already queued for retrieval. Just adding the listener: " + listener);
                imageListeners.add(listener);
            }
        } else {
            debug("Image found in cache. Returning to listener: " + listener);
            listener.onImageReceived(cache.get(key));
        }
    }
    
    private Object downloadImage(String imageUrl) {
        Collection<RemoteImageListener> imageListeners = listeners.get(imageUrl);
        Image image = null;
        try {
            // Get the image and save it in the cache
            URL url = new URL(imageUrl);
            ImageProducer producer = (ImageProducer) url.getContent();
            image = new Panel().createImage(producer);
            cache.put(imageUrl, image);
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            // Notify all listeners with either an image or null
            // Also, remove all listeners from the collection for this image
            for (RemoteImageListener listener : imageListeners) {
                debug("Returning image " + imageUrl + " to listener " + listener);
                listener.onImageReceived(image);
            }
            imageListeners.clear();
            listeners.put(imageUrl, null);
        }
        return null;
    }
}
